package io.github.lee.core.ui

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.MenuRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.core.view.WindowCompat
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import io.github.lee.core.ui.databinding.UiBaseHoverBinding
import io.github.lee.core.ui.databinding.UiBaseLinearBinding
import io.github.lee.core.ui.databinding.UiLayoutProgerssBinding
import io.github.lee.core.util.getDrawable
import io.github.lee.core.util.toPx
import io.github.lee.core.vm.BaseViewModel
import io.github.lee.core.vm.data.UiEvent
import io.github.lee.core.vm.data.UiState
import io.github.lee.core.vm.err.ViewModelException
import kotlinx.coroutines.runBlocking
import razerdp.basepopup.BasePopupWindow

open class BaseFragment<VB : ViewDataBinding, VM : BaseViewModel> : Fragment() {
    protected val mContext: Context by lazy { requireActivity() }
    protected open var isHover = false

    protected var vm: VM? = null

    protected lateinit var toolbarFrameLayout: FrameLayout
        private set
    protected lateinit var contentFrameLayout: FrameLayout
        private set

    protected val toolbar: Toolbar? by lazy { onCreateToolbar() }
    protected var loadingVb: ViewDataBinding? = null// by lazy { onCreateLoading() }
    protected var vb: VB?  = null//by lazy { onCreateSuccess() }
    protected var emptyVb: ViewDataBinding? = null
    protected var errorVb: ViewDataBinding? = null

    //===Desc:======================================================================================
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        vm = onCreateViewModel()?.value
        vm?.also {
            this@BaseFragment.lifecycle.addObserver(it)
        }
        onInitData(savedInstanceState)

    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = if (isHover) {
            val v = UiBaseHoverBinding.inflate(inflater)
            toolbarFrameLayout = v.flToolbarRoot
            toolbarFrameLayout.fitsSystemWindows = true
            contentFrameLayout = v.flContentRoot
            v
        } else {
            val v = UiBaseLinearBinding.inflate(inflater)
            toolbarFrameLayout = v.flToolbarRoot
            contentFrameLayout = v.flContentRoot
            v
        }
        return root.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //加载子类布局
        if (null != toolbar) {
            toolbarFrameLayout.setBackgroundColor(Color.TRANSPARENT)
            toolbarFrameLayout.removeAllViews()
            toolbarFrameLayout.addView(toolbar)
            toolbar?.title = ""
            val a = activity
            if (a is AppCompatActivity) {
                a.setSupportActionBar(toolbar)
            }
            toolbarFrameLayout.visibility = View.VISIBLE
        } else {
            toolbarFrameLayout.visibility = View.GONE
        }

        contentFrameLayout.removeAllViews()
        loadingVb =onCreateLoading()
        loadingVb?.also {
            it.lifecycleOwner = this@BaseFragment
            contentFrameLayout.addView(it.root)
        }
        vb=onCreateSuccess()
        vb?.also {
            val viewParent = vb?.root?.parent
            if (viewParent is ViewGroup) {
                viewParent.removeView(vb?.root)
            }
            it.lifecycleOwner = this@BaseFragment
            contentFrameLayout.addView(it.root)
        }
        emptyVb = onCreateEmpty()
        emptyVb?.also {
            it.lifecycleOwner = this@BaseFragment
            contentFrameLayout.addView(it.root)
        }
        errorVb = onCreateError()
        errorVb?.also {
            it.lifecycleOwner = this@BaseFragment
            contentFrameLayout.addView(it.root)
        }
        Log.e("TAG","aaa =${vm==null}")

//        loadingVb?.root?.visibility=View.GONE
//        vb?.root?.visibility=View.GONE
//        emptyVb?.root?.visibility=View.GONE
//        errorVb?.root?.visibility=View.GONE

        onObserved()

        //判断状态显示
        contentFrameLayout.visibility = View.VISIBLE
        if (null != loadingVb) {
            if (null == vm) {
                showLoading()
            } else {
                vm?.emitUiState(UiState.Loading())
            }
        } else {
            if (null != vb) {
                if (null == vm) {
                    showSuccess()
                } else {
                    vm?.emitUiState(UiState.Success)
                }
            } else {
                if (null != emptyVb) {
                    if (null == vm) {
                        showEmpty()
                    } else {
                        vm?.emitUiState(UiState.Empty())
                    }
                } else {
                    if (null != errorVb) {
                        if (null == vm) {
                            showError()
                        } else {
                            vm?.emitUiState(UiState.Error())
                        }
                    } else {//子类没有实现任何布局，隐藏
                        contentFrameLayout.visibility = View.INVISIBLE
                    }
                }
            }
        }

        onSetViewListener()
        onSetViewData()

    }


    override fun onDestroyView() {
        super.onDestroyView()
        if (null != vm) {
            lifecycle.removeObserver(vm!!)
        }
        loadingVb?.apply { lifecycleOwner = null }
        vb?.apply { lifecycleOwner = null }
        emptyVb?.apply { lifecycleOwner = null }
        errorVb?.apply { lifecycleOwner = null }
    }

    //===Desc:======================================================================================
//    protected open fun onCreateViewModel(): VM? = null
    protected open fun onCreateViewModel(): Lazy<VM>? = null

    protected open fun onCreateToolbar(): Toolbar? = null
    protected open fun onCreateLoading(): ViewDataBinding? = null
    protected open fun onCreateSuccess(): VB? = null
    protected open fun onCreateEmpty(): ViewDataBinding? = null
    protected open fun onCreateError(): ViewDataBinding? = null

    //===Desc:======================================================================================

    protected open fun onInitData(savedInstanceState: Bundle?) {}
    protected open fun onObserved() {
        vm?.apply {
            collectUiState {
                Log.e("TAG","收集到数据:$it")
                when (it) {
                    UiState.None -> showLoading()
                    is UiState.Loading -> showLoading(it.tip)
                    UiState.Success -> showSuccess()
                    is UiState.Empty -> {
                        showEmpty(it.t)
                    }

                    is UiState.Error -> showError(it.t)
                }

            }
            collectUiEvent {
                Log.e("TAG","event:$it")
                when (it) {
                    UiEvent.None -> {}
                    is UiEvent.ShowProgress -> this@BaseFragment.showProgress(it.tip, it.canDismiss)
                    is UiEvent.HideProgress -> this@BaseFragment.hideProgress(it.runnable)
                    is UiEvent.Toast -> this@BaseFragment.toast(it.msg, it.isLong)

                    is UiEvent.RefreshSuccess -> this@BaseFragment.refreshSuccess(it.hasMore)
                    is UiEvent.RefreshFail -> this@BaseFragment.refreshFail(it.e)
                    is UiEvent.LoadMoreSuccess -> this@BaseFragment.loadMoreSuccess(it.hasMore)
                    is UiEvent.LoadMoreFail -> this@BaseFragment.loadMoreFail(it.e)
                }
            }

            collectSoftKeyboard{
                if (it) {
                    //显示键盘
                }else{
                    // hide
                    io.github.lee.core.util.hideSoftKeyboard(activity?.window?.decorView)
                }
            }
        }

    }


    protected open fun onSetViewListener() {}
    protected open fun onSetViewData() {}
    //===Desc:======================================================================================

    protected open fun showLoading(tip: String? = "") {
        if (null == loadingVb) {
            return
        }
        loadingVb?.root?.visibility = View.VISIBLE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showSuccess() {
        if (null == vb) {
            return
        }
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.VISIBLE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showEmpty(e: ViewModelException? = null) {
        if (null == emptyVb) {
            return
        }
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.VISIBLE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showError(e: ViewModelException? = null) {
        if (null == errorVb) {
            return
        }
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.VISIBLE
    }


    class ProgressPopupWindow(context: Context?) : BasePopupWindow(context) {
        val vb = UiLayoutProgerssBinding.inflate(LayoutInflater.from(context))

        init {
            contentView = vb.root
            width = 100.toPx(getContext())
            height = 100.toPx(getContext())

//            width = ViewGroup.LayoutParams.WRAP_CONTENT
//            height = ViewGroup.LayoutParams.WRAP_CONTENT
        }


        fun setTip(tip: String?) {
            vb.tip = tip
        }
    }

    private val progress by lazy {
        ProgressPopupWindow(this.activity)
    }

    protected open fun showProgress(tip: String? = null, canDismiss: Boolean? = true) {
        progress.setTip(tip)
        if (!progress.isShowing) {
            progress.setBackgroundColor(Color.TRANSPARENT)
            progress.popupGravity = Gravity.CENTER
            progress.setOutSideDismiss(canDismiss ?: true)
            progress.showPopupWindow()
        }
    }

    protected open fun hideProgress(runnable: Runnable? = null) {
        if (progress.isShowing) {
            progress.dismiss()
        }
    }

    protected open fun toast(msg: String? = null, isLong: Boolean = false) {
        if (msg.isNullOrEmpty()) {
            return
        }
        Toast.makeText(mContext, msg, if (isLong) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
            .show()
    }
    protected open fun toast(@StringRes resId: Int? , isLong: Boolean = false) {
        if (null == resId) {
            return
        }
        toast(getString(resId), isLong)
    }

    protected open fun refreshSuccess(hasMore: Boolean? = true) {

    }

    protected open fun refreshFail(e: ViewModelException? = null) {

    }

    protected open fun loadMoreSuccess(hasMore: Boolean? = true) {

    }

    protected open fun loadMoreFail(e: ViewModelException? = null) {

    }


    //===Desc:======================================================================================
    protected fun statusBarColor(
        @ColorInt color: Int,
        isDark: Boolean = false,
        fitsSystem: Boolean = true
    ) {
        val a = activity
        if (a is AppCompatActivity) {
            WindowCompat.setDecorFitsSystemWindows(a.window, fitsSystem)
            a.window.statusBarColor = color
            WindowCompat.getInsetsController(a.window, a.window.decorView)
                .isAppearanceLightStatusBars = isDark
        }

    }

    protected fun navigationBarColor(
        @ColorInt color: Int,
        isDark: Boolean = false
    ) {
        val a = activity
        if (a is AppCompatActivity) {
            a.window.navigationBarColor = color
            WindowCompat.getInsetsController(a.window, a.window.decorView)
                .isAppearanceLightNavigationBars = !isDark
        }
    }

    /**
     * fragment注入Toolbar菜单
     *
     * @param menuRes menu layout id
     * @param onMenuItemSelectedBlock when menu item selected callback
     */
    protected fun injectMenu(
        @MenuRes menuRes: Int,
        onMenuItemSelectedBlock: MenuItem.() -> Boolean
    ) {
        val menuHost: MenuHost = requireActivity()
        menuHost.addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(menuRes, menu)
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
                return onMenuItemSelectedBlock(menuItem)
            }
        }, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }

    protected fun setNavigationIcon(
        @DrawableRes resId: Int,
        @ColorInt tintColor: Int? = null,
        listener: View.OnClickListener? = null
    ) {
        if (null == tintColor) {
            toolbar?.setNavigationIcon(resId)
            toolbar?.setNavigationOnClickListener(listener)
        } else {
            val drawable = getDrawable(resId)
            drawable?.setTint(tintColor)
            setNavigationIcon(drawable, listener)
        }
    }

    protected fun setNavigationIcon(
        drawable: Drawable?,
        listener: View.OnClickListener? = null
    ) {
        toolbar?.navigationIcon = drawable
        toolbar?.setNavigationOnClickListener(listener)
    }

}